package com.ncmmall.api.apis.mall;


import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import com.ncmmall.api.apis.service.Result;
import com.feijin.commons.lang.ArithUtils;
import com.ncmmall.domain.business.advertis.Advertis;
import com.ncmmall.domain.business.advertis.QAdvertis;
import com.ncmmall.domain.business.goods.Goods;
import com.ncmmall.domain.business.goods.channel.GoodsChannel;
import com.ncmmall.domain.business.goods.channel.QGoodsChannel;
import com.ncmmall.domain.business.news.News;
import com.ncmmall.domain.business.news.QNews;
import com.ncmmall.domain.business.subject.QSubjectActivity;
import com.ncmmall.domain.business.subject.SubjectActivity;
import com.ncmmall.querychannel.QueryPage;
import com.ncmmall.querychannel.QueryPageRequest;
import com.ncmmall.querychannel.service.QueryChannelService;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.CacheLoader;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author linxs
 * 首页接口
 */
@RestController
@RequestMapping(value = "/home")
@Slf4j
public class HomeApi {

    @Autowired
    private QueryChannelService queryChannelService;

    @Value("${store.domain}")
    private String storeDomain;

    private final LoadingCache<String, Map<String, Object>> cacheBuilder = CacheBuilder.newBuilder()
            .expireAfterWrite(30, TimeUnit.SECONDS)
            .build(new CacheLoader<String, Map<String, Object>>() {
                @Override
                public Map<String, Object> load(String key) {
                    return queryHomeData();
                }
            });

    /**
     * 首页接口
     */
    @RequestMapping(value = "/index", method = RequestMethod.GET)
    public Result index() {
        Result result = new Result();
        try {
            return result.ok().inject(cacheBuilder.get("home"));
        } catch (Exception e) {
            log.error("[首页获取数据异常]", e);
            return result.fail().setMsg("网络连接失败");
        }
    }

    private Map<String, Object> queryHomeData() {
        List<Advertis> banners = queryChannelService.findAll("select a from Advertis a where a.position = 1 and a.platformType = 0 and a.status = 2 order by a.rank desc ", Advertis.class);
        for (Advertis banner : banners) {
            banner.setImage(storeDomain + "/uploads/" + banner.getImage());
            if (banner.getInnerLinkType() == 4) {
                SubjectActivity subjectActivity = queryChannelService.findOne(QSubjectActivity.subjectActivity.id.eq(banner.getSubjectId()), SubjectActivity.class);
                if (subjectActivity != null) {
                    banner.setSubjectUrl(storeDomain + subjectActivity.getTemplatePath());
                }
            }
        }

        List<GoodsChannel> channels = queryChannelService.findAll(QGoodsChannel.goodsChannel.status.eq(1).and(QGoodsChannel.goodsChannel.recommend.isTrue()).and(QGoodsChannel.goodsChannel.deleteStatus.eq(0)), GoodsChannel.class);
        for (GoodsChannel channel : channels) {
            channel.setIcon(storeDomain + "/uploads/" + channel.getIcon());
            channel.setChildren(null);
        }

        List<News> newses = queryChannelService.findAll(QNews.news.status.eq(2).and(QNews.news.recommend.eq(2)).and(QNews.news.platformType.eq(0)), News.class);
        for (News news : newses) {
            news.setContent(null);
        }

        Advertis bigAdverce = queryChannelService.findOne(QAdvertis.advertis.position.eq(2).and(QAdvertis.advertis.status.eq(2)).and(QAdvertis.advertis.platformType.eq(0)), Advertis.class);
        if (null != bigAdverce) {
            bigAdverce.setImage(storeDomain + "/uploads/" + bigAdverce.getImage());
        }

        List<Advertis> smallAdverces = queryChannelService.findAll(QAdvertis.advertis.position.eq(3).and(QAdvertis.advertis.status.eq(2)).and(QAdvertis.advertis.platformType.eq(0)), Advertis.class);
        smallAdverces.forEach(smallAdverce -> smallAdverce.setImage(storeDomain + "/uploads/" + smallAdverce.getImage()));

        List<Map<String, Object>> subjects = queryChannelService.selectAllMap("select id, name from mall_subject where status = 2  and platformType = 0  order by rank asc", Collections.emptyMap());

        for (Map<String, Object> subject : subjects) {
            List<Map<String, Object>> goodsList = queryChannelService.selectAllMap("select mg.id, mg.goodsNo, mg.name, mg.defaultImage, mg.defaultPrice, mg.marketPrice from mall_goods_subject mgs left join mall_goods mg on mgs.goods_id = mg.id where mg.status = 3 and mgs.subjectId = :subjectId and mgs.platformType=0 order by mgs.`rank` asc ", ImmutableMap.of("subjectId", subject.get("id")));
            goodsList.stream().filter(goods -> goods.get("defaultImage") != null).forEach(goods -> goods.put("defaultImage", storeDomain + "/uploads/" + goods.get("defaultImage")));
            subject.put("goodsSubjects", goodsList);
        }

        QueryPageRequest page = new QueryPageRequest().setPageNo(1).setPageSize(10);

        QueryPage<Map<String, Object>> recommendGoodsPage = queryChannelService.selectPageMap("select id, goodsNo, name, defaultImage, defaultPrice, marketPrice from mall_goods where recommend = true and status = 3 and isSupplier = 0 and marketingType = 0 order by recommendTime desc ", page);
        List<Map<String, Object>> recommendGoods = recommendGoodsPage.getResult();

        for (Map<String, Object> recommendGood : recommendGoods) {
            if (null != recommendGood.get("defaultImage")) {
                recommendGood.put("defaultImage", storeDomain + "/uploads/" + recommendGood.get("defaultImage"));
            }
        }

        Map<String, Object> data = new HashMap<>();
        data.put("banners", banners);
        data.put("channels", channels);
        data.put("newses", newses);
        data.put("bigAdverce", bigAdverce);
        data.put("smallAdverces", smallAdverces);
        data.put("recommendGoods", recommendGoods);
        data.put("subjects", subjects);
        data.put("marketings", builderMarketings());
        data.put("totalCount", builderTotalCount());
        return data;
    }

    /**
     * 平台数据统计
     */
    private Map<String, Object> builderTotalCount() {

        Map<String, Object> data = Maps.newHashMap();

        double totalAmount = queryChannelService.selectSum("select ifnull(sum(u.price),0) from mall_order u where u.payStatus = 1 ", new HashMap<>());
        double shoppingCardMoney = queryChannelService.selectSum("select ifnull(sum(o.shoppingCardMoney),0) from mall_order o where o.payStatus = 1", Collections.emptyMap());

        double monthAmount = queryChannelService.selectSum("select ifnull(sum(u.price),0) from mall_order u where u.payStatus = 1 and date_format(u.createTime, '%Y-%m') = :time ", ImmutableMap.of("time", new SimpleDateFormat("yyyy-MM").format(new Date())));
        double shoppingCardMoneyMonthAmount = queryChannelService.selectSum("select ifnull(sum(o.shoppingCardMoney),0) from mall_order o where o.payStatus = 1 and date_format(o.createTime, '%Y-%m') = :time ", ImmutableMap.of("time", new SimpleDateFormat("yyyy-MM").format(new Date())));

        int totalMember = queryChannelService.selectCount("select count(distinct(u.id)) from security_web_user u where u.role_id = 3 ", new HashMap<>());
        int monthMember = queryChannelService.selectCount("select count(distinct(u.id)) from security_web_user u where u.role_id = 3 and date_format(u.createTime, '%Y-%m') = :time ", ImmutableMap.of("time", new SimpleDateFormat("yyyy-MM").format(new Date())));
        int totalMerchant = queryChannelService.selectCount("select count(distinct(u.id)) from security_web_user u where u.role_id = 4 ", new HashMap<>());
        int totalGoods = queryChannelService.selectCount("select count(distinct(u.id)) from mall_goods u where u.status = 3 ", new HashMap<>());

        data.put("totalAmount", ArithUtils.roundHalfUp(totalAmount + shoppingCardMoney, 2));
        data.put("monthAmount", ArithUtils.roundHalfUp(monthAmount + shoppingCardMoneyMonthAmount, 2));
        data.put("totalMember", totalMember);
        data.put("monthMember", monthMember);
        data.put("totalMerchant", totalMerchant);
        data.put("totalGoods", totalGoods);

        return data;
    }

    /**
     * 获取营销活动
     */
    private Map<String, Object> builderMarketings() {

        Advertis seckillBanner = queryChannelService.findOne(QAdvertis.advertis.position.eq(6).and(QAdvertis.advertis.status.eq(2)), Advertis.class);
        Advertis bargainBanner = queryChannelService.findOne(QAdvertis.advertis.position.eq(7).and(QAdvertis.advertis.status.eq(2)), Advertis.class);
        Advertis presellBanner = queryChannelService.findOne(QAdvertis.advertis.position.eq(8).and(QAdvertis.advertis.status.eq(2)), Advertis.class);
        Advertis groupBookingBanner = queryChannelService.findOne(QAdvertis.advertis.position.eq(9).and(QAdvertis.advertis.status.eq(2)), Advertis.class);

        Map<String, Object> data = new HashMap<>();

        List<Map<String, Object>> bargainGoodses = queryChannelService.selectAllMap("select g.defaultImage, g.bargainPrice,g.defaultPrice from mall_goods g where g.status = 3 and g.marketingType = 1 and g.bargainStatus = 5 limit 2 ", ImmutableMap.of());
        List<Map<String, Object>> seckillGoodses = queryChannelService.selectAllMap("select g.defaultImage, g.seckillPrice,g.defaultPrice from mall_goods g where g.status = 3 and g.marketingType = 2 limit 2 ", ImmutableMap.of());
        List<Map<String, Object>> presellGoodses = queryChannelService.selectAllMap("select g.defaultImage, g.presellPrice,g.defaultPrice from mall_goods g where g.status = 3 and g.marketingType = 3 and g.presellStatus in (5,6,7,8) limit 2 ", ImmutableMap.of());
        List<Map<String, Object>> groupBookingGoodses = queryChannelService.selectAllMap("select g.defaultImage, g.groupBookingPrice,g.defaultPrice from mall_goods g where g.status = 3 and g.marketingType = 4 and g.groupBookingStatus = 5 and g.recommend = true limit 2 ", ImmutableMap.of());

        for (Map<String, Object> bargainGoodse : bargainGoodses) {
            String str = MapUtil.getStr(bargainGoodse, "defaultImage");
            if (StrUtil.isNotBlank(str)) {
                bargainGoodse.put("defaultImage", storeDomain + "/uploads/" + str);
            }
        }

        for (Map<String, Object> seckillGoodse : seckillGoodses) {
            String str = MapUtil.getStr(seckillGoodse, "defaultImage");
            if (StrUtil.isNotBlank(str)) {
                seckillGoodse.put("defaultImage", storeDomain + "/uploads/" + str);
            }
        }

        for (Map<String, Object> presellGoodse : presellGoodses) {
            String str = MapUtil.getStr(presellGoodse, "defaultImage");
            if (StrUtil.isNotBlank(str)) {
                presellGoodse.put("defaultImage", storeDomain + "/uploads/" + str);
            }
        }

        for (Map<String, Object> groupBookingGoodse : groupBookingGoodses) {
            String str = MapUtil.getStr(groupBookingGoodse, "defaultImage");
            if (StrUtil.isNotBlank(str)) {
                groupBookingGoodse.put("defaultImage", storeDomain + "/uploads/" + str);
            }
        }

        Map<String, Object> bargain = new HashMap<>();
        bargain.put("banner", bargainBanner == null ? "" : storeDomain + "/uploads/" + bargainBanner.getImage());
        bargain.put("goodses", bargainGoodses);

        Map<String, Object> seckill = new HashMap<>();
        seckill.put("banner", seckillBanner == null ? "" : storeDomain + "/uploads/" + seckillBanner.getImage());
        seckill.put("goodses", seckillGoodses);

        Map<String, Object> presell = new HashMap<>();
        presell.put("banner", presellBanner == null ? "" : storeDomain + "/uploads/" + presellBanner.getImage());
        presell.put("goodses", presellGoodses);

        Map<String, Object> groupBooking = new HashMap<>();
        groupBooking.put("banner", groupBookingBanner == null ? "" : storeDomain + "/uploads/" + groupBookingBanner.getImage());
        groupBooking.put("goodses", groupBookingGoodses);


        data.put("bargain", bargain);
        data.put("seckill", seckill);
        data.put("presell", presell);
        data.put("groupBooking", groupBooking);

        return data;

    }


    /**
     * 推荐商品列表
     */
    @RequestMapping(value = "/recommends", method = RequestMethod.GET)
    public Result goodsList(@RequestParam(defaultValue = "2") int pageNo, @RequestParam(defaultValue = "10") int pageSize) {
        Result result = new Result();
        try {
            QueryPageRequest pageRequest = new QueryPageRequest().setPageNo(pageNo).setPageSize(pageSize);
            Map<String, Object> map = new HashMap<>();
            String hql = "select g from Goods g where g.recommend = true and g.status = 3 and g.isSupplier = 0 and g.marketingType = 0 order by g.recommendTime desc ";
            QueryPage<Goods> page = queryChannelService.findPage(hql, pageRequest.setParams(map), Goods.class);
            for (Goods goods : page.getResult()) {
                goods.setDefaultImage(storeDomain + "/uploads/" + goods.getDefaultImage());
            }
            return result.ok().inject(page);
        } catch (Exception e) {
            log.error("[分类商品列表获取数据异常]", e);
            return result.fail().setMsg("网络连接失败");
        }
    }


}
